package com.djl.zenithbite.service.shopping.store.impl;

import com.djl.zenithbite.common.request.StoreAddRequest;
import com.djl.zenithbite.common.response.BaseResponse;
import com.djl.zenithbite.common.threadlocal.UserContextHolder;
import com.djl.zenithbite.dto.vo.StoreVO;
import com.djl.zenithbite.entity.*;
import com.djl.zenithbite.repository.ProductCategoryMapper;
import com.djl.zenithbite.repository.ProductCategoryRelationMapper;
import com.djl.zenithbite.repository.ProductMapper;
import com.djl.zenithbite.repository.StoreMapper;
import com.djl.zenithbite.repository.impl.StoreRepositoryImpl;
import com.djl.zenithbite.service.shopping.store.StoreService;
import com.djl.zenithbite.util.check.AssertUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class StoreServiceImpl implements StoreService {

    @Autowired
    private StoreMapper storeMapper;

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private StoreRepositoryImpl storeRepository;

    @Autowired
    private ProductCategoryRelationMapper productCategoryRelationMapper;

    @Autowired
    private ProductCategoryMapper productCategoryMapper;


    @Override
    public BaseResponse<StoreVO> queryById(int storeId) {

        //1. query store info
        Store store = storeMapper.selectByPrimaryKey(storeId);
        AssertUtil.notNull(store,"store info not exists");

        //2. query product info by store id
        ProductExample productExample = new ProductExample();
        ProductExample.Criteria productExampleCriteria = productExample.createCriteria();
        productExampleCriteria.andStoreIdEqualTo(store.getStoreId());


        List<Product> products = productMapper.selectByExampleWithBLOBs(productExample);

        Map<Integer,ProductCategory> productCategoryMap = new HashMap<>();
        Map<Integer,List<Product>> productMap = new HashMap<>();

        //3.query product category
        Optional.ofNullable(products).orElse(new ArrayList<>())
                .forEach(product ->{
                    Integer productId = product.getProductId();
                    ProductCategoryRelationExample productCategoryRelationExample = new ProductCategoryRelationExample();
                    ProductCategoryRelationExample.Criteria criteria = productCategoryRelationExample.createCriteria();
                    criteria.andProductIdEqualTo(productId);

                    List<ProductCategoryRelation> productCategoryRelations = productCategoryRelationMapper.selectByExample(productCategoryRelationExample);

                    Optional.ofNullable(productCategoryRelations).orElse(new ArrayList<>())
                            .forEach(productCategoryRelation -> {
                                Integer categoryId = productCategoryRelation.getCategoryId();
                                if (productCategoryMap.get(categoryId) == null){
                                    productCategoryMap.put(categoryId,productCategoryMapper.selectByPrimaryKey(categoryId));
                                }

                                List<Product> productList = productMap.getOrDefault(categoryId,new ArrayList<>());
                                productList.add(product);
                                productMap.put(categoryId,productList);


                            });

                });

        //4.generate view
        StoreVO storeVO = new StoreVO();
        Map<String, List<Product>> productInfoMap = new HashMap<>();
        storeVO.setStore(store);

        productMap.forEach((key, value) -> productInfoMap.put(productCategoryMap.get(key).getCategoryName(), value));

        storeVO.setProductInfoMap(productInfoMap);

        BaseResponse<StoreVO> response = new BaseResponse();
        response.setCode(BaseResponse.SUCCESS);
        response.setData(storeVO);

        return response;
    }

    @Override
    public BaseResponse<StoreVO> addStore(StoreAddRequest request) {

        Store existsStore = storeRepository.selectByStoreName(request.getStoreName());
        AssertUtil.isNull(existsStore,"Store already exists");

        Store store = buildStore(request);
        storeMapper.insertSelective(store);

        BaseResponse response = new BaseResponse();
        response.setCode(BaseResponse.SUCCESS);
        StoreVO storeVO = new StoreVO();
        storeVO.setStore(store);
        response.setData(storeVO);
        return response;
    }

    @Override
    public BaseResponse<List<StoreVO>> userList() {
        StoreExample storeExample = new StoreExample();
        StoreExample.Criteria storeExampleCriteria = storeExample.createCriteria();
        storeExampleCriteria.andUserIdEqualTo(UserContextHolder.getUserPrimaryId());
        List<Store> stores = storeMapper.selectByExampleWithBLOBs(storeExample);

        BaseResponse<List<StoreVO>> baseResponse = new BaseResponse<>();
        baseResponse.setData(Optional.ofNullable(stores).orElse(new ArrayList<>()).stream().map(store -> {
            StoreVO storeVO = new StoreVO();
            storeVO.setStore(store);
            return storeVO;
        }).collect(Collectors.toList()));
        return baseResponse;
    }

    @Override
    public BaseResponse<StoreVO> updateStore(StoreAddRequest request) {
        // 1. 基础参数校验
        AssertUtil.notNull(request, "请求参数不能为空");
        AssertUtil.isNotBlank(request.getStoreName(), "店铺名称不能为空");
        AssertUtil.isNotBlank(request.getAddress(), "店铺地址不能为空");
        AssertUtil.isNotBlank(request.getPhone(), "店铺电话不能为空");
        AssertUtil.notNull(request.getStatus(), "店铺状态不能为空");
        AssertUtil.notNull(request.getDeliveryFee(), "配送费不能为空");
        AssertUtil.isNotBlank(request.getLogoUrl(), "店铺logo不能为空");
        AssertUtil.isNotBlank(request.getBannerUrl(), "店铺banner不能为空");


        // 2. 校验店铺是否存在
        Store existsStore = storeMapper.selectByPrimaryKey(request.getStoreId());
        AssertUtil.notNull(existsStore, "店铺不存在");

       // 3. 校验营业时间
        if (request.getOpenTime() != null && request.getCloseTime() != null) {
            AssertUtil.isTrue(!request.getCloseTime().before(request.getOpenTime()),
                    "结束时间不能早于开始时间");
        }


        Store store = buildStore(request);
        store.setStoreId(request.getStoreId());

        storeMapper.updateByPrimaryKeySelective(store);


        BaseResponse<StoreVO> response = new BaseResponse<>();
        StoreVO storeVO = new StoreVO();
        storeVO.setStore(store);
        response.setCode(BaseResponse.SUCCESS);
        response.setData(storeVO);
        return response;
    }

    private Store buildStore(StoreAddRequest request){
        Store store = new Store();
        store.setUserId(UserContextHolder.getUserPrimaryId());
        store.setStoreName(request.getStoreName());
        store.setAddress(request.getAddress());
        store.setPhone(request.getPhone());
        store.setLogoUrl(request.getLogoUrl());
        store.setBannerUrl(request.getBannerUrl());
        store.setStatus(request.getStatus());
        store.setOpenTime(request.getOpenTime());
        store.setCloseTime(request.getCloseTime());
        store.setDeliveryFee(request.getDeliveryFee());
        store.setMinOrderAmount(request.getMinOrderAmount());
        store.setLatitude(request.getLatitude());
        store.setLongitude(request.getLongitude());
        store.setCreatedAt(new Date());
        store.setUpdatedAt(new Date());
        store.setStoreDesc(request.getStoreDesc());
        return store;

    }
}
